package com.maolong.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.maolong.server.exception.FileFailException;
import com.maolong.server.exception.SaveFailException;
import com.maolong.common.consitant.ResultConstant;
import com.maolong.mapper.ProdDetailMapper;
import com.maolong.mapper.ProductMapper;
import com.maolong.pojo.dto.BarcodeDTO;
import com.maolong.pojo.dto.ProdDetailDTO;
import com.maolong.pojo.entity.ProdDetail;
import com.maolong.pojo.entity.Product;
import com.maolong.pojo.vo.BarcodeVO;
import com.maolong.service.IProdDetailService;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.MDC;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author maolong
 * @since 2025-02-09
 */
@Service
public class ProdDetailServiceImpl implements IProdDetailService {
    @Autowired
    ProdDetailMapper prodDetailMapper;
    @Autowired
    ProductMapper productMapper;

    @Override
    @Transactional
    public void upload(MultipartFile file){
        Workbook workbook = null;
        try {
            workbook = new XSSFWorkbook(file.getInputStream());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        Sheet sheet = workbook.getSheetAt(0);
            int lastRowNum = sheet.getLastRowNum();
            for (int i = 3; i <= lastRowNum; i++) {

                Row row = sheet.getRow(i);
                String num = row.getCell(0).getNumericCellValue()+"";
                ProdDetail prodDetail = new ProdDetail();
                prodDetail.setAddTime(row.getCell(1).getDateCellValue());
                prodDetail.setLocaltion(row.getCell(2).getStringCellValue()); //获取位置数据
                prodDetail.setCode(row.getCell(3).getStringCellValue()); //获取商品代码
                prodDetail.setName(row.getCell(4).getStringCellValue()); //获取商品名称
                prodDetail.setType(row.getCell(5).getStringCellValue()); //获取商品型号
                prodDetail.setPurpose(row.getCell(6).getStringCellValue()); //获取商品用途
                prodDetail.setInNumber((int) row.getCell(7).getNumericCellValue());//获取商品入库数量
                prodDetail.setOutNumber((int) row.getCell(8).getNumericCellValue()); //获取商品出库数量
                prodDetail.setRemain((int) row.getCell(9).getNumericCellValue()); //获取商品剩余数量;
                prodDetail.setUnit(row.getCell(10).getStringCellValue()); //获取商品单位
                prodDetail.setAddUser(row.getCell(11).getStringCellValue()); //获取商品添加人
                prodDetail.setRemark(row.getCell(12).getStringCellValue()); //获取商品备注
                prodDetail.setAddTime(new Date());
                prodDetail.setMonth(new Date().getMonth()+1);

                prodDetailMapper.insert(prodDetail);

                //查看改商品是否存在，存在，那么更新库存，不存在，新插入了
                Product ifProd = productMapper.selectOne(new QueryWrapper<Product>().eq("code", prodDetail.getCode()));
                if(ifProd!=null){
                    if(ifProd.getInventory()<prodDetail.getOutNumber()){
                        throw new FileFailException("第"+num+"行"+prodDetail.getName()+"库存不足,请修改后再上传");
                    }
                    ifProd.setInventory(ifProd.getInventory()+prodDetail.getInNumber()-prodDetail.getOutNumber()); //更新库存
                    ifProd.setInventoryRemove(ifProd.getInventoryRemove()+prodDetail.getOutNumber()); //更新出库
                    ifProd.setInventorySum(ifProd.getInventorySum()+prodDetail.getInNumber()); //更新入库
                    ifProd.setEditTime(prodDetail.getAddTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
                    productMapper.updateById(ifProd);
                }else{
                    if(prodDetail.getOutNumber()>0){
                        throw new FileFailException("第"+num+"行"+prodDetail.getName()+"该商品不存在，无法出库");
                    }
                    Product product = new Product().builder()
                            .code(prodDetail.getCode())
                            .name(prodDetail.getName())
                            .alarm(0)
                            .alarmValue(10)
                            .inventory(prodDetail.getInNumber())
                            .inventoryRemove(0)
                            .inventorySum(prodDetail.getInNumber())
                            .img("url")
                            .localtion(prodDetail.getLocaltion())
                            .type(prodDetail.getType())
                            .unit(prodDetail.getUnit())
                            // TODO 这里应该要改的,id改为从excel中的
                            .addUser(Long.valueOf(MDC.get(ResultConstant.USER_ID)))
                            .addTime(LocalDateTime.now())
                            .editUser(Long.valueOf(MDC.get(ResultConstant.USER_ID)))
                            .editTime(LocalDateTime.now())
                            .build();
                    productMapper.insert(product);
                }
            }


    }

    /**
     * 下载文件
     */
    @Override
    public void download(HttpServletResponse response) {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=inventory.xlsx");

        List<ProdDetail> prodDetails = prodDetailMapper.selectList(null);

        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("template/报表模板.xlsx");

        try {
            XSSFWorkbook sheets = new XSSFWorkbook(resourceAsStream);
            XSSFSheet sheet = sheets.getSheetAt(0);

            for(int i=0;i<prodDetails.size();i++){
                ProdDetail prodDetail = prodDetails.get(i);
                Row row=sheet.createRow(i+3);
                row.createCell(0).setCellValue(prodDetail.getId());
                row.createCell(1).setCellValue(prodDetail.getAddTime());
                row.createCell(2).setCellValue(prodDetail.getLocaltion());
                row.createCell(3).setCellValue(prodDetail.getCode());
                row.createCell(4).setCellValue(prodDetail.getName());
                row.createCell(5).setCellValue(prodDetail.getType());
                row.createCell(6).setCellValue(prodDetail.getPurpose());
                row.createCell(7).setCellValue(prodDetail.getInNumber());
                row.createCell(8).setCellValue(prodDetail.getOutNumber());
                row.createCell(9).setCellValue(prodDetail.getRemain());
                row.createCell(10).setCellValue(prodDetail.getUnit());
                row.createCell(11).setCellValue(prodDetail.getAddUser());
                row.createCell(12).setCellValue(prodDetail.getRemark());
            }
            ServletOutputStream outputStream = response.getOutputStream();
            sheets.write(outputStream);
            outputStream.flush();
            outputStream.close();
            sheets.close();

        } catch (IOException e) {
            throw new RuntimeException(e);
        }




    }

    /**
     * 实现出入库操作
     * @param prodDetailDTO
     */
    @Transactional
    @Override
    public void save(ProdDetailDTO prodDetailDTO) {
        ProdDetail prodDetail = new ProdDetail();
        BeanUtils.copyProperties(prodDetailDTO, prodDetail);
        //获取出入库数量，方便后续使用
        Integer num = Integer.valueOf(prodDetailDTO.getNum());
        Integer remain = Integer.valueOf(prodDetailDTO.getRemain());

        prodDetail.setAddUser(MDC.get(ResultConstant.USER_NAME));
        prodDetail.setAddTime(new Date());
        prodDetail.setMonth(new Date().getMonth()+1);

        //判断是入库还是出库
        if(prodDetailDTO.getInOrOut().equals("入库")){
            prodDetail.setInNumber(num);
            prodDetail.setOutNumber(0);
            productMapper.updateAddByConditions(prodDetailDTO);
        }else{
            if(num> remain)
                throw new SaveFailException("库存不足");

            prodDetail.setOutNumber(num);
            prodDetail.setInNumber(0);
            productMapper.updateRemoveByConditions(prodDetailDTO);
        }

        prodDetail.setId(null);
        prodDetail.setRemain(remain);
        prodDetailMapper.insert(prodDetail);

        //更新预警信息
        productMapper.updateAlarm(1);
        productMapper.updateAlarm(0);

    }

    /**
     * 根据传进来的url图片内容实现相应的更新
     * 其实可以复用代码，但是为了方便理解，以及省事，就分开写了
     * @param barcodeDTO
     */
    // TODO 返回进行更改数据的信息，在前端进行显示
    @Transactional
    @Override
    public BarcodeVO updateBarcode(BarcodeDTO barcodeDTO) {
        String barcodeResult = barcodeDTO.getBarcodeResult();
        int index = barcodeResult.indexOf("+");
        String id=barcodeResult.substring(0,index);
        String code = barcodeResult.substring(index+1);

        //查询改商品是否存在，
        Product product = productMapper.selectOne(new QueryWrapper<Product>().eq("id", id).eq("code", code));
        if(product==null){
            throw new SaveFailException("改商品码不存在，请检查后再扫描");
        }

        ProdDetail prodDetail = new ProdDetail().builder()
                .code(code)
                .localtion(barcodeDTO.getLocaltion())
                .remark(barcodeDTO.getRemark())
                .localtion(product.getLocaltion())
                .name(product.getName())
                .remain(product.getInventory())
                .type(product.getType())
                .unit(product.getUnit())
                .addTime(new Date())
                .build();

        if(barcodeDTO.getInOrOut().equals("入库")){
            prodDetail.setInNumber(1);
            product.setInventory(product.getInventory()+1);
            product.setInventorySum(product.getInventorySum()+1);
        }else{
            prodDetail.setOutNumber(1);
            if(product.getInventory()<1){
                throw new SaveFailException(product.getName()+"库存不足");
            }else{
                product.setInventory(product.getInventory()-1);
                product.setInventoryRemove(product.getInventoryRemove()+1);
            }
            product.setEditTime(LocalDateTime.now());
            // TODO 没整编辑人的信息
        }

        prodDetail.setMonth(new Date().getMonth()+1);
        //插入明细表
        prodDetailMapper.insert(prodDetail);
        //更新商品表
        productMapper.updateById(product);


        //更新预警信息
        productMapper.updateAlarm(1);
        productMapper.updateAlarm(0);

        return new BarcodeVO(product.getId(),product.getName(),barcodeDTO.getInOrOut(),1);

    }
}
